import os.path
import pandas as pd
from datatoolsobj.excel.excelreader import ExcelReader
from datatoolsobj.excel.excelformat import XlsxWriterFormat
from datatoolsobj.utils import create_dir
import logging

logging.basicConfig(level="DEBUG")
mylog = logging.getLogger()

def default_walk_excel_headers_func(data,file_info):
    '''遍历所有Excel表的头部部分时应用的函数原型。
    默认输出每个表的文件信息及头部数据。
    data:每个表的头部数据
    file_info:存在于ExcelDirWalk中的关于此表的信息。
    '''
    print(file_info)
    print(data)

class ExcelHub():
    def __init__(self,excel_dir_dataframe,used_sheet_columns_conf_path,from_excel_used_columns=None,use_exist=True,conf_dir='conf'):
        self._edd = excel_dir_dataframe
        if self._edd.empty:
            raise ValueError("Excel 目录数据表为空！")

        #生成保存指定目录中所有Excel文件使用配置表信息的Excel文件 
        if used_sheet_columns_conf_path and (-1 != used_sheet_columns_conf_path.find(".xls") or -1 != used_sheet_columns_conf_path.find(".xls") ):
            self._uscol_conf_path = used_sheet_columns_conf_path
        elif used_sheet_columns_conf_path:
            self._uscol_conf_path = used_sheet_columns_conf_path+".xlsx"
        else:
            raise FileNotFoundError("给出的Excel表配置文件路径为空！！")

        if not conf_dir:
            self._conf_dir = "conf"
        else:
            self._conf_dir = conf_dir
        create_dir(conf_dir)

        #此处需要加入判断，如果存在配置文件，则需要根据参数确定是不直接使用
        self._conf_path = os.path.join(self._conf_dir,self._uscol_conf_path)
        if os.path.exists(self._conf_path) and use_exist:
            self.inUsedSheetColumnsConfFile()
            self._new_dir = False
        else:
            #此处为新读取文件结构
            self._getExcelSheetHeaderInfo() 
            self._analySheetColumns()
            #此处加入根据参考配置文件修改本配置文件功能
            #修改self._columns_detail_df
            if from_excel_used_columns:
                mylog.debug("从其他项目配置文件[{}]中获取使用表配置信息".format(from_excel_used_columns))
                to_data = self._columns_detail_df
                from_file_path = os.path.join(self._conf_dir, from_excel_used_columns + ".xlsx")
                from_data = pd.read_excel(from_file_path, sheet_name='列使用配置', header=1, dtype={'Sheet表名': 'str'})
                for index,row in to_data.iterrows():
                    to_file_path = row['文件路径']
                    to_year = row['年度']
                    to_flag = row['标记']
                    to_template_type = row['模板类型']
                    to_sheet_name = row['Sheet表名']
                    to_column_name = row['列名']
                    to_row_index = row['列名行位置']
                    to_col_index = row['列名列位置']
                    find_from_row = from_data.loc[(from_data['文件路径']==to_file_path)&(
                            from_data['年度']==to_year)&(from_data['标记']==to_flag)&(from_data['模板类型'] == to_template_type)
                            &(from_data['Sheet表名']==to_sheet_name)&(from_data['列名']==to_column_name)&
                            (from_data['列名行位置']==to_row_index)&(from_data['列名列位置']==to_col_index)]
                    if not find_from_row.empty:
                        to_data.iloc[index,[9,10,11,12]] = find_from_row.iloc[0,[9,10,11,12]]
            self._new_dir = True

    def getUsedSheetColumnsDataFrame(self):
        return self._columns_detail_df
    
    def walkExcelHeaders(self,apply_func=default_walk_excel_headers_func):
        '''遍历每个Sheet表的文件头部分内容，对其应用指定的函数。
        '''
        sheet_path_df = self._columns_detail_df.loc[:,['文件编号','文件路径','年度','标记','模板类型','Sheet表名','列名行位置']]
        walk_df = sheet_path_df.drop_duplicates()
        result = []
        for _,line in walk_df.iterrows():
            data = pd.read_excel(line['文件路径'],header=None,sheet_name=str(line['Sheet表名']),nrows=line['列名行位置'])
            result.append(apply_func(data,line))
        return result

    def _getExcelSheetHeaderInfo(self):
        self._excel_hdr_infos = []
        for index,line in self._edd.iterrows():
            mylog.debug('分析文件{}头部结构'.format(line['Sheet表名']))
            sheet_hdr_info = {}
            sheet_hdr_info['file_id'] = line['文件编号']
            sheet_hdr_info['file_path'] = line['文件路径']
            sheet_hdr_info['sheetname'] = line['Sheet表名']
            sheet_hdr_info['year'] = line['年度']
            sheet_hdr_info['flag'] = line['标记']
            er = ExcelReader(sheet_hdr_info['file_path'])
            hdr = er.detectHeader(sheet_hdr_info['sheetname'])
            sheet_hdr_info.update(hdr)
            self._excel_hdr_infos.append(sheet_hdr_info)
    
    def _analySheetColumns(self):
        '''获取文件基本信息列表中的所有文件列标题,并进行一致性分析。
        excel_infos:由函数analysis_excels返回的文件基本结构信息表。
        返回：（columns_detail_df，columns_count_df）
              @columns_detail_df：描述列名对应结构内容的详细信息表。
              @columns_count_df：所有列名统计分析表。
        '''
        #获取所有文件中列名表
        columns_detail_columns = ['文件编号','文件路径','年度','标记','模板类型','Sheet表名','列名','列名行位置','列名列位置','是否使用','使用别名','列名的别名','列数据类型']
        columns_detail_df = pd.DataFrame(columns=columns_detail_columns)
        for file_item in self._excel_hdr_infos:
            mylog.debug('分析文件{}/{}列名信息'.format(file_item['file_path'],file_item['sheetname']))
            temp_list = []
            file_id = file_item['file_id']
            file_path = file_item['file_path']
            file_sheet = file_item['sheetname']
            file_year = file_item['year']
            file_flag = file_item['flag']
            file_hdr_type = file_item['file_hdr_type']
            file_columns = file_item['columns']['columns_item']
            file_columns_pos = file_item['columns']['columns_pos']
            file_column_index = file_item['columns_index']
            file_columns_type = file_item['columns_type']
            for index,column_item in enumerate(file_columns):
                temp_list.append([file_id,file_path,file_year,file_flag,file_hdr_type,file_sheet,column_item,file_column_index,file_columns_pos[index],'是','否','',file_columns_type[index]])
            temp_df = pd.DataFrame(temp_list,columns=columns_detail_columns)

            if not columns_detail_df.empty and not temp_df.empty:
                columns_detail_df = pd.concat([columns_detail_df,temp_df],ignore_index=True)
            elif not temp_df.empty:
                columns_detail_df = temp_df.copy()
            else:
                all_df = all_df
    
        #不要在只有一个分组依据的时候使用列表作为参数给出，否则将会产生FutureWarning
        groups = columns_detail_df.groupby('列名')
    
        #分析所有列名的出现次数，确定需要映射的列
        columns_count = []
        for gp_id,gp_data in groups:
            columns_count.append([gp_id,gp_data['列名'].count()])
        columns_count_df = pd.DataFrame(columns_count,columns=['列名','出现次数'])
    
        #查找需要映射的列，标记
        need_map = columns_count_df.loc[columns_count_df['出现次数']<len(self._excel_hdr_infos)]
        if not need_map.empty:
            for index,line in need_map.iterrows():
                columns_detail_df.loc[columns_detail_df['列名']==line['列名'],['使用别名']] = '是'

        self._columns_detail_df = columns_detail_df
        self._columns_count_df = columns_count_df  

    def outUsedSheetColumnsConfFile(self,used_sheet_columns_conf_path=None):                  
        '''获取一组Excel文件基本信息列表中的所有文件列标题,并进行一致性分析。然后把结果输出，以便配置使用的列。
        excel_infos:由函数analysis_excels返回的文件基本结构信息表。
        '''
        if used_sheet_columns_conf_path:
            if (-1 != used_sheet_columns_conf_path.find(".xls") or -1 != used_sheet_columns_conf_path.find(".xls") ):
                self._uscol_conf_path = used_sheet_columns_conf_path
            else:
                self._uscol_conf_path = used_sheet_columns_conf_path+".xlsx"

        path = os.path.join(self._conf_dir,self._uscol_conf_path)

        colunmn_width = {'列名':30,'出现次数':20}
        with XlsxWriterFormat(path) as xw:
            xw.to_excel(self._columns_detail_df,'列使用配置',title='列使用配置')
            xw.to_excel(self._columns_count_df,'列名分析',colunmn_width=colunmn_width,title='列名分析')

    def inUsedSheetColumnsConfFile(self,used_sheet_columns_conf_path=None): 
        if used_sheet_columns_conf_path:
            if (-1 != used_sheet_columns_conf_path.find(".xls") or -1 != used_sheet_columns_conf_path.find(".xls") ):
                self._uscol_conf_path = used_sheet_columns_conf_path
            else:
                self._uscol_conf_path = used_sheet_columns_conf_path+".xlsx"

        path = os.path.join(self._conf_dir,self._uscol_conf_path)
        data = pd.read_excel(path,sheet_name='列使用配置',header=1,dtype={'Sheet表名':'str'})
        self._columns_detail_df = data.loc[data['是否使用'].isin(['是','Y',True,'TRUE','True'])]
        self._columns_count_df = pd.read_excel(path,sheet_name='列名分析',header=1)

    def isNewDir(self):
        return self._new_dir

